package com.puff.jdbc.core;

import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.puff.framework.utils.StringUtil;
import com.puff.jdbc.statement.CommentStatement;
import com.puff.jdbc.statement.ForeachStatement;
import com.puff.jdbc.statement.IsEmptyStatement;
import com.puff.jdbc.statement.IsEqualStatement;
import com.puff.jdbc.statement.IsNotEmptyStatement;
import com.puff.jdbc.statement.IsNotEqualStatement;
import com.puff.jdbc.statement.SqlStatement;
import com.puff.jdbc.statement.Statement;
import com.puff.jdbc.statement.TextStatement;

/**
 * 语法构建
 *
 */
public class StatementBuilder {

	/**
	 * 构建SqlStatement
	 * @param sqlnode
	 * 	SQL节点
	 * @return
	 * 
	 */
	public static SqlStatement builder(Node sqlnode) {
		SqlStatement sqlNodeStatement = new SqlStatement(sqlnode);
		buildChild(sqlNodeStatement, sqlnode.getChildNodes());
		return sqlNodeStatement;
	}

	/**
	 * 构建语法树
	 * @param statement
	 * 	statement
	 * @param nodeList
	 * 	子节点
	 */
	private static void buildChild(Statement statement, NodeList nodeList) {
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node node = nodeList.item(i);
			String tag = node.getNodeName().toLowerCase();
			if ("#text".equals(tag)) {
				String content = node.getTextContent();
				content = content.replace("\n", "").trim();
				if (StringUtil.empty(content)) {
					continue;
				} else {
					node.setTextContent(content + " ");
				}
			}
			Statement nodeStatement = createStatement(node);
			if (node.getChildNodes().getLength() > 0) {
				buildChild(nodeStatement, node.getChildNodes());
			}
			statement.addChild(nodeStatement);
		}
	}

	/**
	 * 将XML的NODE节点，转成语法节点
	 * @param node
	 * 	节点
	 * @return
	 * 	Statement
	 */
	private static Statement createStatement(Node node) {
		String tag = node.getNodeName().toLowerCase();
		Class<? extends Statement> clazz = registerMap.get(tag);
		if (clazz != null) {
			try {
				return clazz.getConstructor(new Class[] { Node.class }).newInstance(node);
			} catch (Exception e) {
				throw new RuntimeException("创建" + clazz + "异常!", e);
			}
		}
		throw new RuntimeException(tag + "标签无法识别");
	}

	private static Map<String, Class<? extends Statement>> registerMap = new HashMap<String, Class<? extends Statement>>();

	static {
		registerMap.put("foreach", ForeachStatement.class);
		registerMap.put("empty", IsEmptyStatement.class);
		registerMap.put("notempty", IsNotEmptyStatement.class);
		registerMap.put("equals", IsEqualStatement.class);
		registerMap.put("notequals", IsNotEqualStatement.class);
		registerMap.put("#text", TextStatement.class);
		registerMap.put("#comment", CommentStatement.class);
	}

	/**
	 * 注册标签处理方式
	 * @param tag
	 * 	标签名称
	 * @param clazz
	 * 	处理的Statement
	 */
	public static void register(String tag, Class<? extends Statement> clazz) {
		registerMap.put(tag, clazz);
	}

	/**
	 * 注册
	 * @param tag
	 * 	标签名称
	 * @param clazz
	 * 	处理的Statement
	 */
	@SuppressWarnings("unchecked")
	public static void register(String tag, String clazz) {
		try {
			registerMap.put(tag, (Class<? extends Statement>) Class.forName(clazz));
		} catch (Exception e) {
			throw new RuntimeException(clazz + "注册失败!", e);
		}
	}

}
